package javaMSCRM;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Image;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumnModel;
/**
 * 
 */

import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlString;

import com.microsoft.schemas.crm._2006.query.AllColumns;
import com.microsoft.schemas.crm._2006.query.ArrayOfAnyType;
import com.microsoft.schemas.crm._2006.query.ArrayOfConditionExpression;
import com.microsoft.schemas.crm._2006.query.ArrayOfOrderExpression;
import com.microsoft.schemas.crm._2006.query.ConditionExpression;
import com.microsoft.schemas.crm._2006.query.ConditionOperator;
import com.microsoft.schemas.crm._2006.query.FilterExpression;
import com.microsoft.schemas.crm._2006.query.LogicalOperator;
import com.microsoft.schemas.crm._2006.query.OrderExpression;
import com.microsoft.schemas.crm._2006.query.OrderType;
import com.microsoft.schemas.crm._2006.query.PagingInfo;
import com.microsoft.schemas.crm._2006.query.QueryExpression;
import com.microsoft.schemas.crm._2006.webservices.BusinessEntity;
import com.microsoft.schemas.crm._2006.webservices.BusinessEntityCollection;
import com.microsoft.schemas.crm._2007.webservices.Account;
import com.microsoft.schemas.crm._2007.webservices.Contact;
import com.microsoft.schemas.crm._2007.webservices.EntityName;
import com.microsoft.schemas.crm._2007.webservices.RetrieveMultipleDocument;
import com.microsoft.schemas.crm._2007.webservices.Transactioncurrency;
import com.microsoft.schemas.crm._2007.webservices.RetrieveMultipleDocument.RetrieveMultiple;

/**
 * @author Zoran IVANOV
 *
 */
public class LookupRecords extends JFrame implements ActionListener {
	private static final long serialVersionUID = 1L;

	JavaMSCRM JavaMSCRM = null;
	LookupField LookupField = null;
	ArrayList<String> EntriesIDList = new ArrayList<String>();
	String Entity = null;
	String[] ColumnEntitiesNames = {};
	String[] ColumnEntitiesTitles = {};
	int SortingColumn = 0;
	int SortingDirection = 1;
	PagingInfo pageInfo = null;
	Condition[] MSCRMConditions = {};
	String searchString = "";
	   
	//Controls Definitions
    JPanel 	HeaderBarContainer,SearchBarContainer,SearchContainer,FooterBarContainer,PagingContainer,
    		FooterBarContainerRight;
    JLabel PageNumber;
    JButton SearchButton,JBOk,JBCancel,JBRemoveValue, NextPage, PreviousPage;
    JTextField SearchField = new JTextField(20);
    JComboBox JCBEntityName = new JComboBox();
   
    //Table
    TableModel model = new TableModel();   
    JTable table = new JTable(model);
    JScrollPane TableScrollPane = new JScrollPane(table); 
    JTableHeader TableHeader = table.getTableHeader();

	/**
	 * @author Zoran IVANOV
	 *
	 */
	class ColumnHeaderListener extends MouseAdapter {
		  public void mouseClicked(MouseEvent evt) {
			  JTableHeader tblh = (JTableHeader) evt.getSource();
			  TableColumnModel cm = tblh.getColumnModel();

			  int index = cm.getColumnIndexAtX(evt.getX());
			  if (index == -1) {
			      return;
			  }
		  }
	}
	
	/**
	 * @param mSCRMConditions
	 */
	public void setMSCRMConditions(Condition[] mSCRMConditions) {
		MSCRMConditions = mSCRMConditions;
	}
	
	/**
	 * @param columnEntitiesNames
	 */
	public void setColumnEntitiesNames(String[] columnEntitiesNames) {
		ColumnEntitiesNames = columnEntitiesNames;
	}

	/**
	 * @param columnEntitiesTitles
	 */
	public void setColumnEntitiesTitles(String[] columnEntitiesTitles) {
		ColumnEntitiesTitles = columnEntitiesTitles;
	}
	
	/**
	 * @author Zoran
	 *
	 */
	public class JavaMSCRMStatusBarButton extends JButton {
		private static final long serialVersionUID = 1L;
		public JavaMSCRMStatusBarButton(String label) {
			setText(label);
			setFont(new Font("Arial", Font.PLAIN, 11));
			setPreferredSize(new Dimension(20, 18));
			setMargin(new Insets(0,0,0,0));
		}

	}

	/**
	 * @param JavaMSCRM
	 * @param LookupField
	 */
	public LookupRecords(JavaMSCRM JavaMSCRM, LookupField LookupField) {
		this.JavaMSCRM = JavaMSCRM;
		this.LookupField = LookupField;
		this.Entity = this.LookupField.EntityName;
		this.setTitle("Look Up Records");
		setSize(400,500);
		Image img = Toolkit.getDefaultToolkit().getImage("C:/Users/Zoran/workspace/JavaMSCRM/src/icon.png");
		setIconImage(img);	
		
		HeaderBarContainer = new JPanel(new BorderLayout(0,0));
		JCBEntityName.addItem(EntityName.ACCOUNT.toString());
		JCBEntityName.addItem(EntityName.CONTACT.toString());
		JCBEntityName.addItem(EntityName.TRANSACTIONCURRENCY.toString());
		if(this.Entity.equals(EntityName.ACCOUNT.toString())){
			JCBEntityName.setSelectedItem(EntityName.ACCOUNT.toString());
		}else if(this.Entity.equals(EntityName.CONTACT.toString())){
			JCBEntityName.setSelectedItem(EntityName.CONTACT.toString());
		}else if(this.Entity.equals(EntityName.TRANSACTIONCURRENCY.toString())){
			JCBEntityName.setSelectedItem(EntityName.TRANSACTIONCURRENCY.toString());
		}
		JCBEntityName.setEnabled(false);
		
		HeaderBarContainer.add(JCBEntityName, BorderLayout.LINE_START);
		HeaderBarContainer.add(SearchField);
		SearchButton = new JButton("Search");
		SearchButton.setPreferredSize(new Dimension(80, 20));
		HeaderBarContainer.add(SearchButton, BorderLayout.LINE_END);
		
		 //Footer
	    PageNumber = new JLabel("");
	    PagingContainer = new JPanel();
	    PreviousPage = new JavaMSCRMStatusBarButton("<");
		PreviousPage.setVisible(false);
		PageNumber = new JLabel("");
		NextPage = new JavaMSCRMStatusBarButton(">");
		NextPage.setVisible(false);
		PagingContainer.add(PreviousPage);
		PagingContainer.add(PageNumber);
		PagingContainer.add(NextPage);

	    FooterBarContainer = new JPanel(new BorderLayout(0,0));
	    FooterBarContainerRight = new JPanel();
	    JBOk = new JButton("Ok");
	    JBOk.setPreferredSize(new Dimension(50, 20));
	    JBOk.addActionListener(this);
	    JBCancel = new JButton("Cancel");
	    JBCancel.setPreferredSize(new Dimension(80, 20));
	    JBCancel.addActionListener(this);
	    JBRemoveValue = new JButton("Remove Value");
	    JBRemoveValue.setPreferredSize(new Dimension(120, 20));
	    JBRemoveValue.addActionListener(this);
	    
	    FooterBarContainerRight.add(JBOk);
	    FooterBarContainerRight.add(JBCancel);
	    FooterBarContainerRight.add(JBRemoveValue);
	    
	    FooterBarContainer.add(PagingContainer, BorderLayout.LINE_START);
	    FooterBarContainer.add(FooterBarContainerRight, BorderLayout.LINE_END);
	    
	    add(FooterBarContainer, BorderLayout.PAGE_END);
		
		
		if(this.Entity.equals(EntityName.CONTACT.toString())){
			setColumnEntitiesNames(new String[]{"fullname"});
			setColumnEntitiesTitles(new String[]{"Contact Name"});
		}else if(this.Entity.equals(EntityName.TRANSACTIONCURRENCY.toString())){
			setColumnEntitiesNames(new String[]{"currencyname"});
			setColumnEntitiesTitles(new String[]{"Currency"});
		}else{//Account is default search
			setColumnEntitiesNames(new String[]{"name"});
			setColumnEntitiesTitles(new String[]{"Account Name"});
		}
		
		initialiseSearchForm();		
		displayEntitiesList(pageInfo, 0, 1);		
		
		//Header
		add(HeaderBarContainer, BorderLayout.PAGE_START); 	
		//Table
	    table.setShowVerticalLines(false);

	    setVisible(true);
	}
	
	/**
	 * @param pageInfo
	 * @param sortingColumn
	 * @param sortingDirection
	 */
	public void displayEntitiesList(PagingInfo pageInfo, int sortingColumn, int sortingDirection){
	 	this.SortingColumn = sortingColumn;
	 	this.SortingDirection = sortingDirection;
	 	EntriesIDList = new ArrayList<String>();
	 	String showFieldName = "";
	 	if(this.Entity.equals(EntityName.CONTACT.toString())){
	 		showFieldName = "fullname";
		}else if(this.Entity.equals(EntityName.TRANSACTIONCURRENCY.toString())){
			showFieldName = "currencyname";
		}else if(this.Entity.equals(EntityName.ACCOUNT.toString())){
			showFieldName = "name";
		}
	 	setMSCRMConditions(new Condition[]{
				new Condition(!searchString.equals(""), showFieldName, ConditionOperator.LIKE, "%"+searchString+"%"),
				new Condition(true, "statecode", ConditionOperator.EQUAL, "Active")
				});
	 	
		try {	
            //Table Headers
            displayTableHeader();
            
            add(TableScrollPane, BorderLayout.CENTER);
		    //Rows click Listener
		    table.addMouseListener(new MouseAdapter(){
		        public void mouseClicked(MouseEvent e){
		        	int row = table.getSelectedRow();
		        	if (e.getClickCount() == 2){
	    				LookupField.setValue(EntriesIDList.get(row), table.getValueAt(row, 0).toString());
	    				dispose();
		            }
		         }
		        } );
		    
		    //Retrieve Records
            BusinessEntityCollection bec = JavaMSCRM.stub.RetrieveMultiple(getListOfEntities(pageInfo),  JavaMSCRM.catd, null, null).getRetrieveMultipleResponse().getRetrieveMultipleResult(); 
            BusinessEntity[] Records = bec.getBusinessEntities().getBusinessEntityArray(); 
            
            //Display Records
            if(Records.length > 0){
	            for(int i=0; i<Records.length; i++){
	            	if(this.Entity.equals(EntityName.CONTACT.toString())){
	            		Contact Record = (Contact) Records[i];
		                model.addRow(new Object[]{Record.getFullname()});
		                EntriesIDList.add(Record.getContactid().getStringValue());
	        		}else if(this.Entity.equals(EntityName.TRANSACTIONCURRENCY.toString())){
	        			Transactioncurrency Record = (Transactioncurrency) Records[i];
		                model.addRow(new Object[]{Record.getCurrencyname()});
		                EntriesIDList.add(Record.getTransactioncurrencyid().getStringValue());
	        		}else if(this.Entity.equals(EntityName.ACCOUNT.toString())){
	        			Account Record = (Account) Records[i];
		                model.addRow(new Object[]{Record.getName(), Record.getTelephone1(), Record.getEmailaddress1(), Record.getAddress1City() });
		                EntriesIDList.add(Record.getAccountid().getStringValue());
	        		}	            	
	            }
            }else{
            	JOptionPane.showMessageDialog(null, "No records available in this view!");
            }
            
            //Initialize Letter Filter and Page Navigation
            initialiseLetterFilterAndNavigation(bec);      
              
	        table.setVisible(true);
		}  
		catch (Exception e) {
			JOptionPane.showMessageDialog(null, e.toString());
		}    	
	}
	
	/**
	 * @param bec
	 */
	public void initialiseLetterFilterAndNavigation(BusinessEntityCollection bec){      		        
        //Page Number
        int CurrentPageNumber = this.pageInfo.getPageNumber();
        PageNumber.setText("Page "+Integer.toString(CurrentPageNumber));
        
        //Pages Navigation
        pagesNavigation(bec.getMoreRecords(), CurrentPageNumber);
        
	}
	
	/**
	 * 
	 */
	public void displayTableHeader(){
		String iconUp = " ▲";
        String iconDown = " ▼";
        
        clearTable();
        for(int i=0; i<ColumnEntitiesTitles.length; i++){
        	if((SortingColumn == i)){
            	if(SortingDirection == 1)
            		model.addColumn(ColumnEntitiesTitles[i]+iconDown);
            	else
            		model.addColumn(ColumnEntitiesTitles[i]+iconUp);	
            }else{
            	model.addColumn(ColumnEntitiesTitles[i]);
            }
        }
        
        //Set Action Listeners for Sorting
        
        JTableHeader tableHeader = table.getTableHeader();	
        tableHeader.setFont(new Font("Arial", Font.BOLD, 12));
        tableHeader.addMouseListener(new MouseAdapter(){
	        public void mouseClicked(MouseEvent e){
	        	TableColumnModel columnModel = table.getColumnModel();
	            int viewColumn = table.columnAtPoint(e.getPoint());
	            if((SortingColumn == columnModel.getColumn(viewColumn).getModelIndex()) && (SortingDirection == 1)){
	            	SortingDirection = 2;
	            }else{
	            	SortingDirection = 1;
	            }
	            	
	            SortingColumn = columnModel.getColumn(viewColumn).getModelIndex();
	            displayEntitiesList(null, SortingColumn, SortingDirection);
	         }
	        } );
	}
	
	/**
	 * @param pageInfo
	 * @return com.microsoft.schemas.crm._2007.webservices.RetrieveMultipleDocument
	 */
	public RetrieveMultipleDocument getListOfEntities(PagingInfo pageInfo){
		//Order
        ArrayOfOrderExpression orders = ArrayOfOrderExpression.Factory.newInstance();
        OrderExpression order1 = orders.insertNewOrder(0);
        
        //order1.setAttributeName("name");
        order1.setAttributeName(ColumnEntitiesNames[SortingColumn]);
        order1.setOrderType(OrderType.Enum.forInt(SortingDirection));
        orders.setOrderArray(0,order1);
        
        //Criteria
        FilterExpression criteria = FilterExpression.Factory.newInstance();
        ArrayOfConditionExpression conditions = criteria.addNewConditions(); 
        //Apply Conditions
        for(int i=0; i < MSCRMConditions.length; i++){
        	Condition currentMSCRMCondition = MSCRMConditions[i];
        	if(currentMSCRMCondition.applicationCondition){   
    	        ConditionExpression cExpression = conditions.addNewCondition();
    	        cExpression.setAttributeName(currentMSCRMCondition.attributeName);   
    	        cExpression.setOperator(currentMSCRMCondition.ConditionOperator);
    	        ArrayOfAnyType cValues = cExpression.addNewValues();
    	        cValues.addNewValue();
    	        XmlObject value = XmlString.Factory.newValue(currentMSCRMCondition.value);
    	        cValues.setValueArray(0, value);
            }
        }
       
        criteria.setFilterOperator(LogicalOperator.AND);
        criteria.setConditions(conditions);
        
        QueryExpression query = QueryExpression.Factory.newInstance();
        // Initialize the page number.
    	if(pageInfo == null){
    		this.pageInfo = query.addNewPageInfo();
    		this.pageInfo.setPageNumber(1);
    		this.pageInfo.setCount(JavaMSCRM.recordsPerPage);
    		this.pageInfo.setPagingCookie(null);
		}
    	
    	//Setup the query
        query.setCriteria(criteria);
        query.setDistinct(false);
        query.setColumnSet(AllColumns.Factory.newInstance());  
        query.setEntityName(this.Entity);
        query.setPageInfo(this.pageInfo);
        query.setOrders(orders);
        
        RetrieveMultipleDocument rmd = RetrieveMultipleDocument.Factory.newInstance();  
        RetrieveMultiple rm = RetrieveMultiple.Factory.newInstance();
        rm.setQuery(query);
        rmd.setRetrieveMultiple(rm);
		return rmd;
	}
	
	/**
	 * @param fetchNext
	 * @param CurrentPageNumber
	 */
	public void pagesNavigation(boolean fetchNext, int CurrentPageNumber){
		//Previous Page
        if(CurrentPageNumber > 1){
        	ActionListener[] JBALS = PreviousPage.getActionListeners();
    		for(int i=0; i<JBALS.length; i++){  
    			PreviousPage.removeActionListener(JBALS[i]);
            }
        	PreviousPage.addActionListener(new ActionListener() {
    			public void actionPerformed(ActionEvent e) {
    				pageInfo.setPageNumber(pageInfo.getPageNumber()-2);
    				displayEntitiesList(pageInfo, SortingColumn, SortingDirection);
    			}
    		});
        	PreviousPage.setVisible(true);
        }else{
        	PreviousPage.setVisible(false);
        }
        
        //Next Page
        final PagingInfo pageInfoNextFinal = pageInfo;
        int NextPageNumber = CurrentPageNumber+1;
        pageInfoNextFinal.setPageNumber(NextPageNumber);
        
        if(fetchNext){
        	ActionListener[] JBALS = NextPage.getActionListeners();
    		for(int i=0; i<JBALS.length; i++){  
    			NextPage.removeActionListener(JBALS[i]);
            }
        	NextPage.addActionListener(new ActionListener() {
    			public void actionPerformed(ActionEvent e) {
    				displayEntitiesList(pageInfoNextFinal, SortingColumn, SortingDirection);
    			}
    		});
        	NextPage.setVisible(true);
        }else{
        	NextPage.setVisible(false);
        }
	}
	
	/**
	 * 
	 */
	public void initialiseSearchForm(){
		//Search
		ActionListener[] JBALS = this.SearchButton.getActionListeners();
		for(int i=0; i<JBALS.length; i++){  
			this.SearchButton.removeActionListener(JBALS[i]);
        }
		
		final JButton searchButton = this.SearchButton;
		final JTextField searchField = SearchField;
		searchButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				searchString = searchField.getText();
				if(!searchString.equals("")){
					displayEntitiesList(null, 0, 1);
				}
			}
		});	
	}
		
	/**
	 * 
	 */
	public void clearTable(){
		remove(table);
		remove(TableScrollPane);
        model = new TableModel();
        table = new JTable(model);
	    TableScrollPane = new JScrollPane(table);
	    ((JComponent)getContentPane()).revalidate();
	}

	/* (non-Javadoc)
	 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
	 */
	public void actionPerformed(ActionEvent e) {
		if (e.getSource () == JBOk){
			int[] SelectedRows = table.getSelectedRows();
			if(SelectedRows.length > 0){
				LookupField.setValue(EntriesIDList.get(SelectedRows[SelectedRows.length-1]), table.getValueAt(SelectedRows[SelectedRows.length-1], 0).toString());				
				dispose();
			}
		}else if(e.getSource () == JBCancel){
			this.dispose();
		}else if(e.getSource () == JBRemoveValue){
			LookupField.setValue("", "");			
			dispose();
		}		
	}
}
